/*
	This script file is part of the Sonic 3 A.I.R. script software distribution.
	Copyright (C) 2017-2024 by Eukaryot

	Published under the GNU GPLv3 open source software license, see license.txt
	or https://www.gnu.org/licenses/gpl-3.0.en.html
*/



//-------------------------------------------------------//
// Main menu background                                 //
//-------------------------------------------------------//

global s16 MainMenuBG.scrollOffset		// Scrolling x-position; usually 0, except during certain transitions
global s16 MainMenuBG.logoPosition		// "Sonic 3 A.I.R." logo x-position

function void MainMenuBG.Run()
{
	global.game_mode = 0x0c			// Main Game
	global.zone_act = 0x0d01		// Outro for Sonic/Tails

	// Load the required level patterns for the outro
	//  -> This is essentially the same as "fn007812", but without the call to "waitForNextFrame", and hard-coded 0x1cfb44 to simplify things
	{
		A4 = MainGame.getLevelDataPointer()
		A1 = 0x1cfb44
		D4.u16 = u16[A1]
		Kosinski.addToDMAQueue(A1, 0x0000)

		while (true)
		{
			global.frame_state = 0x0c
			Kosinski.ProcessDecompressionQueue()

			LoadRequiredSpritePatterns()
			Kosinski.ProcessModules()
			if (kosinski.waiting_modules == 0)
				break
		}
	}

	// Load level chunks and stuff
	fn01c2b0()

	// Load plane contents
	camera.foreground.x.u16 = 0x0280
	camera.foreground.y.u16 = 0
	camera.background.x.u16 = 0
	camera.background.y.u16 = 0x0800
	fillPlane_DefaultUncropped(0xc000, camera.foreground.x.u16, camera.foreground.y.u16, 512, getScreenHeight())
	fillPlane_DefaultUncropped(0xe000, camera.background.x.u16, camera.background.y.u16, 512, getScreenHeight())
	camera.foreground.x.u16 += 22		// Move camera a few pixels to the right by default
	u16 cameraForegroundX = camera.foreground.x.u16
	u16 cameraBackgroundX = camera.background.x.u16

	// Flip the right half of certain lines in plane B, to make the ocean waves look more seamless
	constant array<u16> LINE_VRAM_ADDRESS =
	{
		0xec40, 0xecc0, 0xedc0
	}
	for (u16 lineIndex = 0; lineIndex < 3; ++lineIndex)
	{
		u16 addr = LINE_VRAM_ADDRESS[lineIndex]
		for (u16 i = 0; i < 0x20; i += 2)
		{
			u16 pattern1 = getVRAM(addr + i)
			u16 pattern2 = getVRAM(addr + 0x3e - i)
			setVRAM(addr + i, pattern2 ^ 0x800)
			setVRAM(addr + 0x3e - i, pattern1 ^ 0x800)
		}
	}

	// Write vertical scroll offsets to VSRAM
	VDP.setupVSRAMWrite(0)
	VDP.writeData16(0x4c)								// Foreground vertical scroll offset (Angel Island)
	VDP.writeData16(camera.background.y.u16 & 0xff)		// Background vertical scroll offset (sky & ocean)

	// Setup palette
	copyPaletteDataFromTable(0x03, 0xfc00)
	copyMemory(0xfffffc20, 0x05b16e, 0x20)
	copyMemory(0xfffffc40, 0x0a97bc, 0x20)
	copyMemory(0xfffffc60, 0x0a983c, 0x20)

	u32[0xffffa800] = 0x00738000		// Basically a timer for the animation; don't start at 0, that doesn't look all that nice

	while (true)
	{
		MainMenuBG.Update(cameraForegroundX, cameraBackgroundX)

		yieldExecution()
		++level.framecounter
	}
}


function void MainMenuBG.Update(u16 cameraForegroundX, u16 cameraBackgroundX)
{
	Renderer.resetSprites()

	// Ocean palette effect
	fn05928c()
	VDP.copyToCRAMbyDMA(0xfffffc00, 0x0000, 0x80)

	// Scrolling for water and clouds
	{
		camera.foreground.x.u16 = cameraForegroundX + MainMenuBG.scrollOffset
		u16[0xffffee98] = cameraBackgroundX + MainMenuBG.scrollOffset

		fn05b0a8()
		u32[0xffffa800] -= 0x0200	// Partially undo the scrolling progress, to make it slightly slower

		A4 = 0x05b15a
		A5 = 0xffffa804
		A1 = 0xffffe000		// Location of linewise scroll offsets
		D0.u16 = 0x0300		// camera.background.y.u16 - 0x0500
		D1.u16 = getScreenHeight() - 1
		D3.u16 = camera.foreground.x.u16
		fn04f0de()

		// Manual correction for two lines with broken scrolling (also in outro)
		u16[0xffffe0ee] = u16[0xffffe0f2]
		u16[0xffffe16e] = u16[0xffffe172]
		VDP.copyToVRAMbyDMA(0xffffe000, 0xf000, getScreenHeight() * 4)
	}

	Renderer.drawCustomSprite("sonic3air_logo", MainMenuBG.logoPosition, 11, 0, 0, 0xa000)
}
